﻿using Shop.Model.DB;
using Shop.Model.GoodsSku;
using Shop.RemoteModel.GoodsSku.Model;
using Shop.Repository.LinqHelper;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.IdGenerator;
using WeDonekRpc.Model;
using WeDonekRpc.SqlSugar;

namespace Shop.Repository.lmpl
{
    internal class GoodsSkuRepository : ShopBaseRepository<DBGoodsSku, long>, IGoodsSkuRepository
    {
        public GoodsSkuRepository (ISqlClientFactory factory) : base(factory)
        {
        }
        public SkuDatum[] Query (SkuQueryParam query, IBasicPage paging, out int count)
        {
            paging.InitOrderBy("SkuId", true);
            return this.JoinQuery<DBGoods, SkuDatum>(query.ToWhere(), null, (a, b) => new SkuDatum
            {
                SkuId = a.SkuId,
                GoodsId = a.GoodsId,
                SkuName = a.SkuName,
                CategoryId = b.CategoryId,
                GoodsStatus = b.Status,
                GoodsSku = a.GoodsSku,
                GoodsName = b.GoodsName,
                SkuImg = a.SkuImg,
                Price = a.Price,
                SpecsShow = a.SpecsShow
            }, paging, out count);
        }
        public SkuDatum[] GetSkuDatums (long[] ids)
        {
            return this.Join<DBGoods, SkuDatum>((a, b) => b.Id == a.GoodsId && ids.Contains(a.SkuId), (a, b) => new SkuDatum
            {
                SkuId = a.SkuId,
                GoodsId = a.GoodsId,
                GoodsStatus = b.Status,
                SkuName = a.SkuName,
                CategoryId = b.CategoryId,
                GoodsSku = a.GoodsSku,
                GoodsName = b.GoodsName,
                SkuImg = a.SkuImg,
                Price = a.Price,
                SpecsShow = a.SpecsShow
            });
        }
        public Result[] GetsByGoodsId<Result> (long[] goodsId) where Result : class, new()
        {
            return base.Gets<Result>(a => goodsId.Contains(a.GoodsId));
        }
        public Result[] GetsByGoodsId<Result> (long goodsId) where Result : class, new()
        {
            return base.Gets<Result>(a => a.GoodsId == goodsId);
        }
        public DBGoodsSku[] GetsByGoodsId (long goodsId)
        {
            return base.Gets(a => a.GoodsId == goodsId);
        }
        public override void Delete (long[] id)
        {
            ISqlQueue<DBGoodsSku> queue = base.BeginQueue();
            queue.Delete(a => id.Contains(a.SkuId));
            queue.Delete<DBGoodsSkuSpec>(a => id.Contains(a.SkuId));
            _ = queue.Submit();
        }

        public DBGoodsSku Find (long goodsId, string specKey)
        {
            return base.Get(a => a.GoodsId == goodsId && a.SpecsKey == specKey);
        }
        public bool Set (DBGoodsSku sku, SkuSet set)
        {
            List<DBGoodsAttr> attrs = this._GetAttrs(sku, set.Attrs);
            ISqlQueue<DBGoodsSku> queue = base.BeginQueue();
            bool isRefresh = queue.Update(sku, set);
            queue.Delete<DBGoodsAttr>(a => a.SkuId == sku.SkuId);
            if (attrs.Count > 0)
            {
                queue.Insert<DBGoodsAttr>(attrs);
            }
            _ = queue.Submit();
            return isRefresh;
        }
        public long Add (SkuAdd add)
        {
            DBGoodsSku sku = add.ConvertMap<SkuAdd, DBGoodsSku>();
            sku.AddTime = DateTime.Now;
            sku.SkuId = IdentityHelper.CreateId();
            DBGoodsSkuSpec[] specs = add.SkuSpec.ConvertAll(a => new DBGoodsSkuSpec
            {
                SkuId = sku.SkuId,
                SpecGroupId = a.SpecGroupId,
                GoodsId = add.GoodsId,
                SpecId = a.SpecId,
                Id = IdentityHelper.CreateId()
            });
            List<DBGoodsAttr> attrs = this._GetAttrs(sku, add.Attrs);
            ISqlQueue<DBGoodsSku> queue = base.BeginQueue();
            queue.Insert(sku);
            queue.Insert<DBGoodsSkuSpec>(specs);
            if (attrs.Count > 0)
            {
                queue.Insert<DBGoodsAttr>(attrs);
            }
            _ = queue.Submit();
            return sku.SkuId;
        }
        private List<DBGoodsAttr> _GetAttrs (DBGoodsSku sku, GoodsAttr[] list)
        {
            List<DBGoodsAttr> attrs = [];
            if (!list.IsNull())
            {
                list.ForEach((c, i) =>
                {
                    DBGoodsAttr attr = new DBGoodsAttr
                    {
                        Id = IdentityHelper.CreateId(),
                        SkuId = sku.SkuId,
                        Sort = i,
                        GoodsId = sku.GoodsId,
                        IsDir = c.IsDir,
                        Name = c.Name,
                        ParentId = 0,
                        Value = c.Value,
                    };
                    attrs.Add(attr);
                    this._InitAttr(attr, c.Attrs, attrs);
                });
            }
            return attrs;
        }
        private void _InitAttr (DBGoodsAttr prt, GoodsAttr[] list, List<DBGoodsAttr> attrs)
        {
            if (!list.IsNull())
            {
                list.ForEach((c, i) =>
                {
                    DBGoodsAttr attr = new DBGoodsAttr
                    {
                        Id = IdentityHelper.CreateId(),
                        SkuId = prt.SkuId,
                        Sort = i,
                        GoodsId = prt.GoodsId,
                        IsDir = c.IsDir,
                        Name = c.Name,
                        ParentId = prt.Id,
                        Value = c.Value,
                    };
                    attrs.Add(attr);
                    this._InitAttr(attr, c.Attrs, attrs);
                });
            }
        }
    }
}
